<?php
declare (strict_types = 1);

namespace app\user\model;

use app\api\model\IdentityCard;
use app\common\model\Config;
use app\common\self\SelfRedis;
use think\facade\Db;
use think\Model;

/**
 * @mixin \think\Model
 */
class UserBank extends Model
{
    public $page = '';//分页数据
    public $count = '';//数据总数
    public $error = '';//报错
    public $field = '';
    public $apiUrl = 'https://ccdcapi.alipay.com/validateAndCacheCardInfo.json?_input_charset=utf-8';
    public $retData = '{"CDB":"国家开发银行","ICBC":"中国工商银行","ABC":"中国农业银行","BOC":"中国银行","CCB":"中国建设银行","PSBC":"中国邮政储蓄银行","COMM":"交通银行","CMB":"招商银行","SPDB":"上海浦东发展银行","CIB":"兴业银行","HXBANK":"华夏银行","GDB":"广东发展银行","CMBC":"中国民生银行","CITIC":"中信银行","CEB":"中国光大银行","EGBANK":"恒丰银行","CZBANK":"浙商银行","BOHAIB":"渤海银行","SPABANK":"平安银行","SHRCB":"上海农村商业银行","YXCCB":"玉溪市商业银行","YDRCB":"尧都农商行","BJBANK":"北京银行","SHBANK":"上海银行","JSBANK":"江苏银行","HZCB":"杭州银行","NJCB":"南京银行","NBBANK":"宁波银行","HSBANK":"徽商银行","CSCB":"长沙银行","CDCB":"成都银行","CQBANK":"重庆银行","DLB":"大连银行","NCB":"南昌银行","FJHXBC":"福建海峡银行","HKB":"汉口银行","WZCB":"温州银行","QDCCB":"青岛银行","TZCB":"台州银行","JXBANK":"嘉兴银行","CSRCB":"常熟农村商业银行","NHB":"南海农村信用联社","CZRCB":"常州农村信用联社","H3CB":"内蒙古银行","SXCB":"绍兴银行","SDEB":"顺德农商银行","WJRCB":"吴江农商银行","ZBCB":"齐商银行","GYCB":"贵阳市商业银行","ZYCBANK":"遵义市商业银行","HZCCB":"湖州市商业银行","DAQINGB":"龙江银行","JINCHB":"晋城银行JCBANK","ZJTLCB":"浙江泰隆商业银行","GDRCC":"广东省农村信用社联合社","DRCBCL":"东莞农村商业银行","MTBANK":"浙江民泰商业银行","GCB":"广州银行","LYCB":"辽阳市商业银行","JSRCU":"江苏省农村信用联合社","LANGFB":"廊坊银行","CZCB":"浙江稠州商业银行","DYCB":"德阳商业银行","JZBANK":"晋中市商业银行","BOSZ":"苏州银行","GLBANK":"桂林银行","URMQCCB":"乌鲁木齐市商业银行","CDRCB":"成都农商银行","ZRCBANK":"张家港农村商业银行","BOD":"东莞银行","LSBANK":"莱商银行","BJRCB":"北京农村商业银行","TRCB":"天津农商银行","SRBANK":"上饶银行","FDB":"富滇银行","CRCBANK":"重庆农村商业银行","ASCB":"鞍山银行","NXBANK":"宁夏银行","BHB":"河北银行","HRXJB":"华融湘江银行","ZGCCB":"自贡市商业银行","YNRCC":"云南省农村信用社","JLBANK":"吉林银行","DYCCB":"东营市商业银行","KLB":"昆仑银行","ORBANK":"鄂尔多斯银行","XTB":"邢台银行","JSB":"晋商银行","TCCB":"天津银行","BOYK":"营口银行","JLRCU":"吉林农信","SDRCU":"山东农信","XABANK":"西安银行","HBRCU":"河北省农村信用社","NXRCU":"宁夏黄河农村商业银行","GZRCU":"贵州省农村信用社","FXCB":"阜新银行","HBHSBANK":"湖北银行黄石分行","ZJNX":"浙江省农村信用社联合社","XXBANK":"新乡银行","HBYCBANK":"湖北银行宜昌分行","LSCCB":"乐山市商业银行","TCRCB":"江苏太仓农村商业银行","BZMD":"驻马店银行","GZB":"赣州银行","WRCB":"无锡农村商业银行","BGB":"广西北部湾银行","GRCB":"广州农商银行","JRCB":"江苏江阴农村商业银行","BOP":"平顶山银行","TACCB":"泰安市商业银行","CGNB":"南充市商业银行","CCQTGB":"重庆三峡银行","XLBANK":"中山小榄村镇银行","HDBANK":"邯郸银行","KORLABANK":"库尔勒市商业银行","BOJZ":"锦州银行","QLBANK":"齐鲁银行","BOQH":"青海银行","YQCCB":"阳泉银行","SJBANK":"盛京银行","FSCB":"抚顺银行","ZZBANK":"郑州银行","SRCB":"深圳农村商业银行","BANKWF":"潍坊银行","JJBANK":"九江银行","JXRCU":"江西省农村信用","HNRCU":"河南省农村信用","GSRCU":"甘肃省农村信用","SCRCU":"四川省农村信用","GXRCU":"广西省农村信用","SXRCCU":"陕西信合","WHRCB":"武汉农村商业银行","YBCCB":"宜宾市商业银行","KSRB":"昆山农村商业银行","SZSBK":"石嘴山银行","HSBK":"衡水银行","XYBANK":"信阳银行","NBYZ":"鄞州银行","ZJKCCB":"张家口市商业银行","XCYH":"许昌银行","JNBANK":"济宁银行","CBKF":"开封市商业银行","WHCCB":"威海市商业银行","HBC":"湖北银行","BOCD":"承德银行","BODD":"丹东银行","JHBANK":"金华银行","BOCY":"朝阳银行","LSBC":"临商银行","BSB":"包商银行","LZYH":"兰州银行","BOZK":"周口银行","DZBANK":"德州银行","SCCB":"三门峡银行","AYCB":"安阳银行","ARCU":"安徽省农村信用社","HURCB":"湖北省农村信用社","HNRCC":"湖南省农村信用社","NYNB":"广东南粤银行","LYBANK":"洛阳银行","NHQS":"农信银清算中心","CBBQS":"城市商业银行资金清算中心"}';

    /*
     * 用户添加银行卡
     */
    public function addCard($id){
        try{
            if(empty($id)) exception('找不到该用户!');
            //按时间筛选
            $data = Input('post.');
            $info = [];
            $bid = 0;
            if(empty($data['name'])||strlen($data['name']) < 5 ||strlen($data['name']) > 16)
                exception('请填写正确的姓名');
            if(empty($data['phone'])||!preg_match("/^1[3456789]\d{9}$/", $data['phone']))
                exception('请填写正确的手机号');
            if(empty($data['identity'])||strlen($data['identity']) < 15 ||strlen($data['identity']) > 18)
                exception('请填写正确的身份证号');
            else
                if(!IdentityCard::isValid($data['identity']))
                    exception('身份证号不正确');
            if(empty($data['card']))
                exception('请填写正确的银行卡号');
            else{
                if($this->field('id')->where(['card'=>$data['card'],'is_delete'=>0])->find())
                    exception('此卡已存在');
                $url = $this->apiUrl."&cardNo={$data['card']}&cardBinCheck=true";
                $ret = curlGet($url);
                $ret = json_decode($ret,true);
                if(isset($ret['validated'])&&$ret['validated'] === true&&$ret['stat']=='ok'){
                    $default = $this->field('id')->where(['uid'=>$id,'is_default'=>1,'is_delete'=>0])->find();
                    $retData = json_decode($this->retData,true);
                    $info = [
                        'uid' => $id,
                        'bank_name' => $retData[$ret['bank']],
                        'code' => $ret['bank'],
                        'address' => '',
                        'card' => $ret['key'],
                        'name' => $data['name'],
                        'identity' => $data['identity'],
                        'phone' => $data['phone'],
                        'type' => (!empty($ret['cardType'])&&$ret['cardType']=='CC') ? 2 : 1,
                        'is_default' => empty($default) ? 1 : 0,
                        'add_time' => time(),
                    ];
                    $bid = $this->insertGetId($info);
                }else
                    exception('非法的银行卡号');
            }
            $resData = [#('.substr($v['card'],-4).') '
                'id'=>$bid,
                'bank_name'=>($info['bank_name']??''),
                'card'=>'尾号 ('.substr(($info['card']??''),-4).((!empty($info['type'])&&$info['type']=='CC') ? ') 信用卡' : ') 储蓄卡'),
                'is_default'=>((!empty($info['is_default'])&&$info['is_default']==1) ? true : false),
            ];
            if(!empty($ret['bank']) && file_exists(app()->getRootPath() .'public'.config('static.read_bank').$ret['bank'].'.png'))
                $resData['img'] = getApiDominUrl(config('static.read_bank').$ret['bank'].'.png');
            else $resData['img'] = getApiDominUrl(config('static.read_bank').'bank.png');
            return $resData;
        }catch (\Exception $e){
            if(stristr($e->getMessage(),'SQLSTATE')){
                $this->error = '数据走丢了，请稍后再试！';
            }else $this->error = $e->getMessage();
            return false;
        }
    }

    /*
     * 校验银行卡信息
     */
    public function checkCard($req=[]){
        try{
            $bank = [];
            $data = Input('post.');
            if(empty($data['card'])&&!empty($req['card'])) $data['card'] = $req['card'];
            if(empty($data['card'])){
                exception('请填写正确的银行卡号');
            }else{
                if($this->field('id')->where(['card'=>$data['card'],'is_delete'=>0])->find())
                    exception('此卡已存在');
                $url = $this->apiUrl."&cardNo={$data['card']}&cardBinCheck=true";
                $ret = curlGet($url);
                $ret = json_decode($ret,true);
                if(isset($ret['validated'])&&$ret['validated'] === true&&$ret['stat']=='ok'){
                    if($ret['cardType']=='CC') exception('请勿添加信用卡');
                    $retData = json_decode($this->retData,true);
                    $bank['bank_name'] = $retData[$ret['bank']];
                    $bank['type'] = (!empty($ret['cardType'])&&$ret['cardType']=='CC') ? '信用卡' : '储蓄卡';
                    $bank['card'] = $data['card'];
                    if(file_exists(app()->getRootPath() .'public'.config('static.read_bank').$ret['bank'].'.png'))
                        $bank['img'] = getApiDominUrl(config('static.read_bank').$ret['bank'].'.png');
                    else $bank['img'] = getApiDominUrl(config('static.read_bank').'bank.png');
                }else
                    exception('非法的银行卡号');
            }
            return $bank;
        }catch (\Exception $e){
            if(stristr($e->getMessage(),'SQLSTATE')){
                $this->error = '数据走丢了，请稍后再试！';
            }else $this->error = $e->getMessage();
            return false;
        }
    }

    /*
     * 获取用户银行卡记录
     */
    public function getMyCard($id){
        try{
            if(empty($id)) exception('找不到该用户!');
            $info = [];
            $data = Input('post.');
            $where[] = ['uid','=',$id];
            if(!empty($data['card'])){
                $where[] = ['card','=',$data['card']];
            }else{
                $withdraw = (new Config())->toData('finance');
                $wallet = (new UserWallet())->getWallet($id);
                $info = [
                    'balance'=>$wallet['balance'],
                    'rate'=>$withdraw['withdraw_formalities'],
                    'list'=>[]
                ];
            }
            $where[] = ['is_delete','=',0];
            $list = $this->field('id,type,bank_name,card,code,is_default')->where($where)->order('is_default desc,add_time desc')->select();
            $list = empty($list) ? array():$list->toArray();
            if(!empty($list)){
                foreach($list as $k=>$v){
                    $type = $v['type'] == 1 ? '储蓄卡' : '信用卡';
                    $info['list'][$k]['id'] = $v['id'];
                    $info['list'][$k]['bank_name'] = $v['bank_name'];
                    $info['list'][$k]['card'] = '尾号 ('.substr($v['card'],-4).') '.$type;
                    $info['list'][$k]['is_default'] = empty($v['is_default'])?false:true;
                    if(file_exists(app()->getRootPath() .'public'.config('static.read_bank').$v['code'].'.png'))
                        $info['list'][$k]['img'] = getApiDominUrl(config('static.read_bank').$v['code'].'.png');
                    else $info['list'][$k]['img'] = getApiDominUrl(config('static.read_bank').'bank.png');
                }
            }
            if(!empty($data['card'])) return $info['list'];
            else return $info;
        }catch (\Exception $e){
            if(stristr($e->getMessage(),'SQLSTATE')){
                $this->error = '数据走丢了，请稍后再试！';
            }else $this->error = $e->getMessage();
            return false;
        }
    }

    /*
     * 新增提现记录
     */
    public function addWithdrawal($user){
        try{
            if(empty($user)) exception('找不到该用户!');
            $data = Input('post.');
            $day = date('w');
            if(in_array($day,[0,6])) exception('请在周一至周五提现!');
            if($user->is_proceeds == 0) exception('请先提升掌柜等级或开通购物券权益!');
            $amount =  (int) $data['amount'];
            if(empty($data['amount'])||$data['amount'] < 0||$data['amount'] != $amount)
                exception('请填写正确的金额，金额需为整数');
            if(empty($data['type'])) $data['type'] = 1;#设置默认类型
            if(!in_array($data['type'],[1,2])) exception('请选择提现类型!');
            if($data['type'] == 1){
                if(empty($data['bank_id']))
                    exception('请选择提现银行卡');
                if(!$this->field('card')->where(['id'=>$data['bank_id'],'uid'=>$user->id,'is_delete'=>0])->find())
                    exception('选择提现的银行卡不存在');
            }elseif($data['type'] == 2&&empty($user->openid)) exception('零钱提现需要先授权微信用户信息!');
            $info = (new Config())->toData('finance');
            if($info['withdraw_min'] > $amount) exception("提现的金额不能低于{$info['withdraw_min']}元");
            elseif($data['amount'] % 50 != 0) exception('提现的金额必须为50的整数倍!');
            if($info['withdraw_max'] < $amount) exception("提现的金额不能高于{$info['withdraw_max']}元");
            $wallet = (new UserWallet())->getWallet($user->id);
            if($amount > $wallet['balance']) exception("余额不足{$amount}元");
            $rateModel = (new Config())->toData('finance');
            $withdrawRate = $rateModel['withdraw_formalities'];
            $rate = $amount*($withdrawRate/100);
            $rate = (int)($rate*100);
            $money = (int) ($amount*100) - $rate;
            $info = [
                'uid'=>$user->id,
                'bid'=>($data['type']==1) ? $data['bank_id'] : 0,
                'type'=>2,
                'withdrawal_type'=>$data['type'],
                'gold'=>(int) ($amount*100),
                'amount'=>$money,
                'rate'=>$rate,
                'status'=>1,
                'add_time'=>time(),
            ];
            $model = new UserCash();
            $this::startTrans();
            if(!$cid = $model->insertGetId($info))
                exception("提现失败");
            if(!Db::name('user_wallet')->dec('balance', (int)($amount*100))->where('uid',$user->id)->update()){
                $model->where(['id'=>$cid])->delete();
                exception("提现失败");
            }
            Db::name('wallet_operation_log')->insertGetId(['uid'=>$user->id,'reward'=>(int)($amount*100),'status'=>2,'type'=>1,'extend'=>'user_cash','extend_id'=>$cid,'describe'=>'余额提现','add_time'=>time()]);
            $this::commit();
            return true;
        }catch (\Exception $e){
            $this::rollback();
            if(stristr($e->getMessage(),'SQLSTATE')){
                $this->error = '数据走丢了，请稍后再试！';
            }else $this->error = $e->getMessage();
            return false;
        }
    }

    /*
     * ORC 银行卡校验
     */
    public function orcBank($id){
        try{
            $data = Input('post.');
            if(!empty($_FILES['img'])){
                if(empty($data['type'])) exception('请选择上传文件类型!');
                $imgInfo = imgUpdate('img','bank',"bank_{$id}");
                if(!isset($imgInfo['result'])) exception($imgInfo['msg']);
                $imgUrl = getApiDominUrl($imgInfo['result']);
                if(filter_var($imgUrl, FILTER_VALIDATE_URL) !== false){
                    $access_token = (new Config())->getAccessToken();
                    $url = "https://api.weixin.qq.com/cv/ocr/bankcard?type=MODE&img_url={$imgUrl}&access_token={$access_token}";
                    $ret = curlPost($url);
                    $retData = json_decode($ret,true);
                    unlink('.'.$imgInfo['result']);
                    if(empty($retData['number'])) exception('图片无法识别');
                    try{
                        $cardInfo = $this->checkCard(['card'=>$retData['number']]);
                        if(empty($cardInfo)) exception($this->error);
                        return $cardInfo;
                    }catch (\Exception $e){
                        exception($e->getMessage());
                    }
                }
            }
            exception('数据有误，请重试!');
            return false;
        }catch (\Exception $e){
            if(stristr($e->getMessage(),'SQLSTATE')){
                $this->error = '数据走丢了，请稍后再试！';
            }else $this->error = $e->getMessage();
            return false;
        }
    }
}
